<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>kml2gmaps.html: Maps KML file onto Google Maps</title>
    <style>
h1 { font-size: 14px; }
body, input { font-size: 12px; font-family: verdana,arial,sans-serif; }
ul#menu { margin: 0 0 0 20px; padding: 0; }
#menu li { list-style-type: none; cursor: pointer; margin: 0; padding: 2px; }
#menu li img { vertical-align: middle; }
div.popup { width: 18em; }
.footer { clear: both; font-size: 10px; padding-top: 10px; }
</style>
    <script src="http://maps.google.com/maps?file=api&v=1&key=ABQIAAAA2SGB7kYAwJ7vNIiGUvsYgBQhPSrtY3c-aq-G7Tm93zGQQxtL5xTnwm2_6ZCVnME0pZzKvB7i8npggw" type="text/javascript"></script>
    <script type="text/javascript">
    //<![CDATA[
    GPoint.prototype.exjp_map_datum = function (datum) {
      if (datum) this._exjp_map_datum = datum;
      return this._exjp_map_datum ? this._exjp_map_datum : GPoint.exjp_judge_tow(this.x,this.y);
    }
    GPoint.prototype.exjp_map_coord = function () {
      return [this.x,this.y];
    }
    GPoint.prototype.exjp_origin_datum = function (datum) {
      if (datum) this._exjp_origin_datum = datum;
      return this._exjp_origin_datum ? this._exjp_origin_datum : 'wgs84';
    }
    GPoint.prototype.exjp_origin_coord = function (x,y) {
      if (x && y) this._exjp_origin_coord = [x,y];
      return this._exjp_origin_coord ? this._exjp_origin_coord : GPoint.exjp_datum_change(this.x,this.y,this.exjp_map_datum,this.exjp_origin_datum);
    }
    GPoint.exjp_create = function(lng,lat,datum,use_simple) {
      var change_method = use_simple ? GPoint.exjp_simple_change : GPoint.exjp_datum_change;
      if (!(datum)) datum = 'wgs84';

      var map_datum = GPoint.exjp_judge_tow(lng,lat);
      var t_coord = change_method(lng,lat,datum,map_datum);
      var ret = new GPoint(t_coord[0],t_coord[1]);
      ret.exjp_map_datum(map_datum);
      ret.exjp_origin_datum(datum);
      return ret;
    }
    
    GPoint.exjp_judge_tow = function (lng,lat) {
      if (lng > 115 && lng < 152 && lat > 30 && lat < 50) {
        return 'tokyo';
      } else {
        return 'wgs84';
      }
    }

    GPoint.exjp_ellip = new Object;
    GPoint.exjp_ellip['wgs84'] = [6378137,(1 / 298.257223),0,0,0];
    GPoint.exjp_ellip['tokyo'] = [6377397.155,(1 / 299.152813),148,-507,-681];

    GPoint.exjp_datum_change = function (lng,lat,from_d,to_d) {
        if (from_d == to_d) return [lng,lat];

        var fellip = GPoint.exjp_ellip[from_d];
        var tellip = GPoint.exjp_ellip[to_d];

        var a_v = [fellip[0],tellip[0]];    // Equatorial Radius
        var f_v = [fellip[1],tellip[1]];    // Flattening

        var dx = tellip[2] - fellip[2];
        var dy = tellip[3] - fellip[3];
        var dz = tellip[4] - fellip[4];

        return GPoint.exjp_molodensky(lng, lat, a_v[0], f_v[0], a_v[1], f_v[1],dx,dy,dz);
    }
    GPoint.exjp_molodensky = function (l,b,a1,f1,a2,f2,dx,dy,dz) {
        var rd = Math.PI/180;

        b *= rd;
        l *= rd;

        var e2 = 2*f1 - f1*f1;  // Square of Eccentricity
        var bda = 1- f1;        // Polar Radius / Equatorial Radius
        var da = a2 - a1;
        var df = f2 - f1;
        var sb = Math.sin(b);
        var cb = Math.cos(b);
        var sl = Math.sin(l);
        var cl = Math.cos(l);

        var rn = 1 / Math.sqrt(1 - e2*sb*sb); 
        var rm = a1 * (1 - e2) * rn * rn * rn;
        rn *= a1;

        // Calcurating Delta Value
        var db = -dx*sb*cl - dy*sb*sl + dz*cb + da*rn*e2*sb*cb/a1 + df*(rm/bda+rn*bda)*sb*cb;
        db /= rm;
        var dl = -dx*sl + dy*cl;
        dl /= rn * cb;

        return [(l+dl)/rd,(b+db)/rd];
    }
    GPoint.exjp_simple_change = function (lng,lat,from_d,to_d) {
      if (from_d == to_d) return [lng,lat];

      if (from_d == 'tokyo') {
        t_lat = lat - 0.00010695*lat + 0.000017464*lng + 0.0046017;
        t_lng = lng - 0.000046038*lat - 0.000083043*lng + 0.010040;
      } else {
        t_lat = lat + 0.00010696*lat - 0.000017467*lng - 0.0046020;
        t_lng = lng + 0.000046047*lat + 0.000083049*lng - 0.010041;
      }
      return [t_lng,t_lat];
    }
    //]]>
    </script>
  </head>
  <body>
    <h1>Maps KML file onto Google Maps <small>(SEE ALSO <a href="http://as-is.net/blog/archives/001032.html">http://as-is.net/blog/archives/001032.html</a>)</small></h1>
    <div id="map" style="width:600px;height:400px;float:left;"></div>
    <div style="width:300px;float:left;"><ul id="menu"></ul></div>
    <p class="footer">Written by <a href="http://as-is.net/blog/">Hirotaka Ogawa</a>. Powered by <a href="http://www.google.com/apis/maps/">Google Maps API</a> and nene-san's Datum-shift code (<a href="http://kokogiko.net/georss-gmaps.cgi?src=1">http://kokogiko.net/georss-gmaps.cgi?src=1</a>).</p>
    <script type="text/javascript">
    //<![CDATA[
    var baseIcon = new GIcon();
    baseIcon.image = "http://labs.google.com/ridefinder/images/mm_20_red.png";
    baseIcon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
    baseIcon.iconSize = new GSize(12, 20);
    baseIcon.shadowSize = new GSize(22, 20);
    baseIcon.iconAnchor = new GPoint(6, 20);
    baseIcon.infoWindowAnchor = new GPoint(5, 1);
      
    var map = new GMap(document.getElementById("map"));
    map.addControl(new GLargeMapControl());
    map.addControl(new GMapTypeControl());

    var menu = document.getElementById("menu");
    function createMarker(point, index, name, desc) {
      var letter = String.fromCharCode("A".charCodeAt(0) + index);
      var marker = new GMarker(point, baseIcon);
      var msg = name ? '<b>' + name + '</b>' + (desc ? '<p>' + desc + '</p>' : '') : 'Marker <b>' + letter + '</b>';
      msg = '<div class="popup">' + msg + '</div>';

      var li = document.createElement("li");
      li.innerHTML = '<img src="' + baseIcon.image + '"> ' + name;

      var f = function() { marker.openInfoWindowHtml(msg); li.style.background = '#DDE'; };
      var g = function() { li.style.background = 'transparent'; }
      GEvent.addListener(marker, "click", f);
      GEvent.addListener(marker, "infowindowclose", g);
      li.onmousedown = f;
      li.onmouseover = function() { li.style.marginLeft = '2px'; }
      li.onmouseout = function() { li.style.marginLeft = '0px'; }

      menu.appendChild(li);
      return marker;
    }

    var request = GXmlHttp.create();
    var url = window.location.search;
    var i = url.indexOf('?url=');
    url = (i != -1) ? url.substr(i+5) : 'http://as-is.net/maps/sample.kml';
    url = 'http://as-is.net/maps/aproxy.cgi?url=' + encodeURIComponent(url);
    request.open("GET", url, true);
    request.onreadystatechange = function() {
      if (request.readyState == 4) {
	var xmlDoc = request.responseXML;
	var markers = xmlDoc.documentElement.getElementsByTagName("Placemark");
	var len = Math.min(markers.length, 20);
	for (var i = 0; i < len; i++) {
	  var lng = parseFloat(markers[i].getElementsByTagName("longitude")[0].childNodes[0].data);
	  var lat = parseFloat(markers[i].getElementsByTagName("latitude")[0].childNodes[0].data);
	  var point = new GPoint.exjp_create(lng, lat);
	  if (!i) map.centerAndZoom(point, 4);
	  var names = markers[i].getElementsByTagName("name");
	  var name = names.length ? names[0].childNodes[0].data : '';
	  var descs = markers[i].getElementsByTagName("description");
	  var desc = descs.length ? descs[0].childNodes[0].data : '';
	  var marker = new createMarker(point, i, name, desc);
	  map.addOverlay(marker);
	}
      }
    }
    request.send(null);
    //]]>
    </script>
  </body>
</html>
